<template>
  <div id="container"></div>
</template>

<script setup>
import { onMounted } from 'vue';
import * as Cesium from 'cesium';
import './Widgets/widgets.css';
import gsap from 'gsap';

// 设置cesium 静态资源路径
window.CESIUM_BASE_URL = '/';

// 天地图 官网申请的key https://console.tianditu.gov.cn/api/key
const webKey = '01fc395160d8eb3b82aefe65b2280e58';

Cesium.Ion.defaultAccessToken =
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmNDkwYWVhOS0wNzI5LTQ3OTEtOWFiMC1kY2M3MTFiM2I2NWQiLCJpZCI6MTkyNTU1LCJpYXQiOjE3MDY1MTM0MTh9.YAPVHr1d7PBuWayCXM9deCxKg3AbtsXUJiVpubVS3NY';

onMounted(async () => {
  // 地球视图，底图加载
  const viewer = new Cesium.Viewer('container', {
    //设置地形
    terrainProvider: Cesium.createWorldTerrain({
      requestWaterMask: true, // 水纹效果  海里面有波浪的效果
      requestVertextNormal: true, // 光照效果
    }),

    //信息窗口
    infoBox: false,
  });

  //隐藏cesium Icon-logo
  viewer.cesiumWidget.creditContainer.style.display = 'none';

  // 自定义材质类型【自定义实现 顶点着色器】MaterialProperty -> https://cesium.com/learn/cesiumjs/ref-doc/MaterialProperty.html?classFilter=material
  class CustomMaterialPropery {
    constructor() {
      this.definitionChanged = new Cesium.Event();
      Cesium.Material._materialCache.addMaterial('CustomMaterial555', {
        fabric: {
          type: 'CustomMaterial555',
          uniforms: {
            uTime: 0,
          },
          /**
       * czm_materialInput 可用的参数如下
        positionToEyeEC：视点到物体的眼睛空间位置向量。
        normalEC：眼睛坐标系下的法线向量。
        tangentToEyeMatrix：切线到眼睛的矩阵。
        str：切线空间的s向量。
        normal：切线空间的法线向量。
        tangent：切线空间的切线向量。
        bitangent：切线空间的副切线向量。
        lightDirectionEC：眼睛坐标系下的光源方向向量。
        h：半向量，即视线方向和光线方向的平均值。
        s：投影纹理坐标的s分量。
        t：投影纹理坐标的t分量。

        czm_material 使用gpt搜索查看具体属性: cesium czm_material 包含哪些内容，分别说明
       */
          // 自定义 着色器
          source: `czm_material czm_getMaterial(czm_materialInput materialInput) 
             {
                  // 生成默认的材质
                  czm_material material = czm_getDefaultMaterial(materialInput);
                  material.diffuse = vec3(materialInput.st, uTime);
                  // material.diffuse = vec3(materialInput.st, 1.0);
                  return material;
              }`,
        },
      });
      this.params = {
        uTime: 0,
      };
      // 动态修改参数值
      gsap.to(this.params, {
        uTime: 1,
        duration: 2,
        repeat: -1,
        yoyo: true, // 循环变化
        ease: 'linear',
      });
    }
    getType() {
      return `CustomMaterial555`;
    }
    getValue(time, result) {
      // 方案一: 动态修改 uniforms.uTime 并更新到 着色器 中
      // let t = performance.now() / 1000;
      // t = t % 1;
      // result.uTime = t;

      // 方案二
      result.uTime = this.params.uTime;

      return result; // 返回材质
    }
  }

  const material555 = new CustomMaterialPropery();

  // 使用entities 创建矩形
  const rectangle = viewer.entities.add({
    name: 'Rectangle',
    // position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 2000),
    rectangle: {
      coordinates: Cesium.Rectangle.fromDegrees(-75.0, 32.0, -45.0, 40.0),
      material: material555, // 材质颜色
      // material: Cesium.Color.RED.withAlpha(0.5), // 材质颜色
      outline: true,
      outlineColor: Cesium.Color.BLACK,
      outlineWidth: 2,
    },
  });

  // 几何体 实例
  const instance = new Cesium.GeometryInstance({
    //primivite 创建矩形 【官网案例】api https://cesium.com/learn/cesiumjs-learn/cesiumjs-geometry-appearances/
    geometry: new Cesium.RectangleGeometry({
      // 创建几何体
      // API https://cesium.com/learn/cesiumjs/ref-doc/RectangleGeometry.html?classFilter=RectangleGeometry
      rectangle: Cesium.Rectangle.fromDegrees(-100.0, 20.0, -70.0, 30.0),
      height: 0,
      // 贴图的 外观和 材质需要是同一个类型
      vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT, // 每个实例的颜色外观
    }),
    attributes: {
      color: new Cesium.ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 0.8),
    },
  });

  const anotherInstance = new Cesium.GeometryInstance({
    geometry: new Cesium.RectangleGeometry({
      rectangle: Cesium.Rectangle.fromDegrees(-65.0, 20.0, -35.0, 30.0),
      vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
    }),
    attributes: {
      color: new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.8),
    },
  });

  // https://cesium.com/learn/cesiumjs/ref-doc/Material.html?classFilter=material
  // api 通过配置的方式，添加材质
  // const maa = new Cesium.Material({
  //   fabric: {
  //     // type: 'Color', // Water  Grid 皆可
  //     // uniforms: {
  //     //   color: new Cesium.Color(1.0, 1.0, 0.0, 1.0),
  //     // },

  //     type: 'DiffuseMap',
  //     uniforms: {
  //       image: './texture/ta.png',
  //     },
  //   },
  // });

  // 自定义编写材质的着色器
  // 【核心文档-很难找到的】https://cesium.com/downloads/cesiumjs/releases/b28/Documentation/
  const maa = new Cesium.Material({
    fabric: {
      type: 'CustomMaterial',
      uniforms: {
        // color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
        uTime: 0,
      },
      /**
       * czm_materialInput 可用的参数如下
        positionToEyeEC：视点到物体的眼睛空间位置向量。
        normalEC：眼睛坐标系下的法线向量。
        tangentToEyeMatrix：切线到眼睛的矩阵。
        str：切线空间的s向量。
        normal：切线空间的法线向量。
        tangent：切线空间的切线向量。
        bitangent：切线空间的副切线向量。
        lightDirectionEC：眼睛坐标系下的光源方向向量。
        h：半向量，即视线方向和光线方向的平均值。
        s：投影纹理坐标的s分量。
        t：投影纹理坐标的t分量。

        czm_material 使用gpt搜索查看具体属性: cesium czm_material 包含哪些内容，分别说明
       */
      // 自定义 着色器
      source: `czm_material czm_getMaterial(czm_materialInput materialInput) {
                  czm_material material = czm_getDefaultMaterial(materialInput);
                  // material.diffuse = vec3(1.0,1.0,0.0); // 自定义修改颜色
                  material.diffuse = vec3(materialInput.st,0.0); // 自定义修改颜色
                  // float strength = mod((materialInput.s + uTime) * 10.0, 1.0); // 往左滚动
                  float strength = mod((materialInput.s - uTime) * 10.0, 1.0); // 往左滚动
                  material.diffuse = vec3(strength,0.0,0.0);
                  // material.alpha = 0.8; // 自定义修改透明度
                  return material;
              }`,
    },
  });

  // 动态修改参数值
  gsap.to(maa.uniforms, {
    uTime: 1,
    duration: 2,
    repeat: -1,
    ease: 'linear',
  });

  console.log(maa.shaderSource);

  // api https://cesium.com/learn/cesiumjs/ref-doc/EllipsoidSurfaceAppearance.html?classFilter=Ellipsoid
  /**
   * 设定几何体都是与🌍的椭球体平行的
   * 假定几何体与地球椭球体平行，那么就可以在计算大量顶点属性的时候节省内存
   */
  const appearance11 = new Cesium.EllipsoidSurfaceAppearance({
    // material: maa,
    // aboveGround: false,
    // translucent: true,

    // 自定义 片元着色器【在外观上，动态设置颜色，片元着色器】
    fragmentShaderSource: `
    varying vec3 v_positionMC;
    varying vec3 v_positionEC;
    varying vec2 v_st;
    uniform float uTime;

    void main()
    {
      czm_materialInput materialInput;

      gl_FragColor = vec4(v_st, uTime, 1.0);
    }
    `,
  });
  appearance11.uniforms = {
    uTime: 0.0,
  }; // 传入片元着色器里头

  // 动态修改 片元着色器 参数值
  gsap.to(appearance11.uniforms, {
    uTime: 1,
    duration: 2,
    repeat: -1,
    yoyo: true, // 往返的渲染动态颜色值
    ease: 'linear',
  });

  console.log(appearance11);
  console.log(appearance11.vertexShaderSource); // 顶点着色器
  console.log(appearance11.fragmentShaderSource); // 片元着色器

  // 添加到场景中 https://cesium.com/learn/cesiumjs-learn/cesiumjs-geometry-appearances/
  viewer.scene.primitives.add(
    // 创建图元
    new Cesium.Primitive({
      geometryInstances: [instance, anotherInstance], // 同时有多个几何体
      appearance: appearance11,
      // appearance: new Cesium.PerInstanceColorAppearance({
      //   flat: true, // 外观平整，贴着球体
      // }),
    })
  );

  // 设置相机位置
  viewer.camera.setView(viewer.entities);
});
</script>

<style scoped>
* {
  padding: 0;
  margin: 0;
}
#container {
  height: 94vh;
  width: 94vw;
}
</style>
